package org.esky.spring.aop;

import java.lang.reflect.Method;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class HelloChinaAspect {
	
	@Before(value = "@annotation(org.esky.spring.aop.HelloAnnotation)")
	public void beforeSayHello(JoinPoint joinPoint) {
		System.out.println("Before : " + joinPoint.getArgs()[0]);
	}
	
	@After(value = "@annotation(org.esky.spring.aop.HelloAnnotation) && @annotation(helloAnnotation)", argNames = "helloAnnotation")
	public void afterSayHello(HelloAnnotation annotation) {
		String message = annotation.value();
		System.out.println("After Annotation : " + message);
	}
	
	@Around(value = "@annotation(org.esky.spring.aop.HelloAnnotation)")
	public Object aroundSayHello(ProceedingJoinPoint joinPoint) throws Throwable {
		System.out.println("Around Before !");
		Signature signature = joinPoint.getSignature();
		System.out.println("Around : " + signature);
		MethodSignature methodSignature = (MethodSignature) signature;
		Method method = methodSignature.getMethod();
		System.out.println("Around Method : " + method);
		boolean bool = method.isAnnotationPresent(HelloAnnotation.class);
		if (bool) {
			HelloAnnotation annotation = method.getAnnotation(HelloAnnotation.class);
			System.out.println("Around Method Annotation : " + annotation.annotationType().getCanonicalName());
			System.out.println("Around Method Annotation value : " + annotation.value());
		}
		Object object = joinPoint.proceed();
		System.out.println("Around After !");
		return object;
	}
	
	@AfterReturning(value = "@annotation(org.esky.spring.aop.HelloAnnotation)", returning = "reval")
	public void afterReturningSayHello(Object reval) {
		System.out.println("After Returning : " + reval);
	}
	
	@AfterThrowing(value = "@annotation(org.esky.spring.aop.HelloAnnotation)", throwing = "ex")
	public void afterThrowingSayHello(Exception ex) {
		System.out.println("After Throwing : " + ex.getMessage());
	}
}
